﻿#include "customlistwidgets.h"
#include "EagleDeviceMgr.h"
#include "QDateTime"
#include "qevent.h"
#include "QTimer"
#include "QWidget"

QStringList RecordList::GenerateCcdRecordRow(EagleData_CcdRecord* ccd_record)
{
	QStringList row;
	row << (QString::number(ccd_record->id.device_id));
	row << (QString::number(ccd_record->id.ccd_serial));
	row << (InterfaceType[ccd_record->pixel_sampling_type != PixelSamplingGrey ? 1 : 0]);
	int column = ccd_record->column;
	int line = ccd_record->line;
	int color_depth = ccd_record->real_color_depth;
	GetRealROIAndColorDepth(ccd_record->pixel_sampling_type, column, line, color_depth);

#ifdef CHENGGS_VERSION 

	if (ccd_record->id.ccd_serial == 3 && CHENGGS_VERSION == 2)
	{
		column /= 2;
		color_depth = (color_depth * 3) / 2;
	}

	if (ccd_record->id.ccd_serial == 2 && CHENGGS_VERSION == 3)
	{
		column /= 4;
		color_depth = (color_depth * 3);
	}

#endif

	row << (QString::number(column));
	row << (QString::number(line));
	row << (QString::number(color_depth));
	row << (QString::number(int(ccd_record->frame_number)));  // long x64 is int
	QString str = QString::fromWCharArray(ccd_record->start_time);
	QDateTime dt = QDateTime::fromString(str, "yyyyMMddhhmmss");
	if (!dt.isValid())  // 年月日为 0 的日期 视为不合理时间
	{
		dt = QDateTime::fromString(str.mid(8), "hhmmss");
	}
	row << dt.toString("yy/MM/dd hh:mm:ss");
	str = QString::fromWCharArray(ccd_record->end_time);
	dt = QDateTime::fromString(str, "yyyyMMddhhmmss");
	if (!dt.isValid())  // 年月日为 0 的日期 视为不合理时间
	{
		dt = QDateTime::fromString(str.mid(8), "hhmmss");
	}
	row << dt.toString("yy/MM/dd hh:mm:ss");

	return row;
}

void RecordList::AppendAllRecord(EagleData_Record_Id* record_id)
{
	int nCount = 0;
	EagleData_CcdRecord* ccd_record = 0;
	EagleData_Record* eagle_record = EagleData_GetRecordAndAllocMemory(*record_id);

	if (eagle_record == NULL)
		return;

	try{

		ccd_record = eagle_record->ccd_record_list;
		while (ccd_record != 0)
		{
			AppendRow(GenerateCcdRecordRow(ccd_record));
			ccd_record = ccd_record->next;
			nCount++;
		}
	}
	catch (std::runtime_error&)
	{
		qDebug() << QString("No record %1 %2").arg(QString::fromWCharArray(eagle_record->id.task_name)).arg(record_id->start_time);
	}

	EagleData_FreeRecordMemory(eagle_record);

}

DevicePopupWindow::DevicePopupWindow(QWidget *parent, int device_id, const eagle_system_status* status, EDeviceType device_type)
:EList(parent, device_list_label, DEVICE_LIST_COLUMN, "DevicePopupWindow")
{
	QStringList content = GenerateDeviceRow(status, device_id, device_type);
	AppendRow(content);
}


CLCcdPopupWindow::CLCcdPopupWindow(QWidget *parent, const eagle_capture_config* ccdconfig, unsigned char diskmap, int device_id, EDeviceType device_type)
: EList(parent, cl_ccd_list_label, CL_CCD_LIST_COLUMN_NUM, "ClCcdPopupWindow")
{
	QStringList content = GenerateCcdRow(ccdconfig, diskmap, /*disk.disk_reign[serial_no - 1], */device_id, device_type);
	AppendRow(content);
}

SDICcdPopupWindow::SDICcdPopupWindow(QWidget *parent, const eagle_capture_config* ccdconfig, unsigned char diskmap, int device_id, EDeviceType device_type)
: EList(parent, sdi_ccd_list_label, SDI_CCD_LIST_COLUMN_NUM, "SdiCcdPopupWindow")
{
	QStringList content = GenerateCcdRow(ccdconfig, diskmap, /*disk.disk_reign[serial_no - 1], */device_id, device_type);
	AppendRow(content);
}

//////////////////////////////////////////////////////////////////////////
// 记录列表 [11/15/2016 ejitec]
recListWidgets::recListWidgets(QWidget *parent)
: baseTreeWidget(parent)
{
	
}

void recListWidgets::heardInit()  // 必须在构造后，setui 之后进行 
{
	setColumnCount(1);
	setHeaderLabels(QStringList() << task_list_label[0]._label); // << tr("操作"));
	connect(this, &QTreeWidget::itemEntered, this, &recListWidgets::on_ItemEnter);
}


recListWidgets::~recListWidgets()
{

}

// 模拟移出事件
void recListWidgets::mouseMoveEvent(QMouseEvent *event)
{
	QTreeWidgetItem* item = itemAt(event->pos());

	if (!item )  // 移出事件 [11/15/2016 ejitec]
	{
		delete _popUpMenu;
		_popUpMenu = NULL;
		return;
	}

	return QTreeWidget::mouseMoveEvent(event);  // 传递该事件 否则 移入受影响
}

void recListWidgets::on_ItemEnter(QTreeWidgetItem* item, int column)
{
	//qDebug() << "recListWidgets::on_ItemEnter:" << item->text(0);

	if (_curItem == item)  // 与上次一致
	{
		return;
	}

	_curItem = item;
	delete _popUpMenu;
	_popUpMenu = NULL;

	if (_curItem->type() == ITEM_PARENT)
	{
		return;
	}

	// 录像列表 
	QVariant data = item->data(0, Qt::UserRole);  // 只取出第一个元素作为录像回放
	EagleData_Record_Id* record_id = data.value<EagleData_Record_Id*>();
	_popUpMenu = new RecordList(this, rec_list_label, REC_LIST_COLUMN_NUM);
	static_cast<RecordList*>(_popUpMenu)->AppendAllRecord(record_id);
	_popUpMenu->setHeight();
	_popUpMenu->exec(this->mapToGlobal(visualItemRect(item).bottomLeft() + QPoint(5,25)));
	//_curItem = nullptr;

}

void recListWidgets::enterEvent(QEvent *event)
{
	//qDebug() << "begin show enterEvent";
	_curItem = nullptr;
	delete _popUpMenu;
	_popUpMenu = NULL;
}
// 
void recListWidgets::leaveEvent(QEvent *event)
{
	//qDebug() << "begin show leaveEvent";
	_curItem = nullptr;
	delete _popUpMenu;
	_popUpMenu = NULL;
}

//  右键事件
void recListWidgets::contextMenuEvent(QContextMenuEvent * event)
{
	QTreeWidgetItem* item = itemAt(event->pos());
	if (!item /*|| item->type() == ITEM_PARENT*/)
	{
		return;
	}

	QMenu menu;
	QAction *replay = menu.addAction(tr("回放"));
	QAction *exp = menu.addAction(tr("导出"));
	QAction *del = menu.addAction(tr("删除"));
	QAction *renam = menu.addAction(tr("重命名"));

	QAction *selectedAction = menu.exec(event->globalPos());

	if (selectedAction == replay)
		emit evt_ActRecReplay();
	else if (selectedAction == exp)
		emit evt_ActRecExport();
	else if (selectedAction == del)
		emit evt_ActRecDel();
	else if (selectedAction == renam)
		emit evt_ActRecRenam();
}

std::vector<void*> recListWidgets::GetSelectedRecords()
{
	std::vector<void*> res;

	QList<QTreeWidgetItem*> items = this->selectedItems();

	for (auto it : items)
	{
		if (it->type() == ITEM_PARENT)
		{
			int nChild = it->childCount();
			for (int i = 0; i < nChild; i++)
			{
				res.push_back(it->child(i)->data(0, Qt::UserRole).value<EagleData_Record_Id*>());
			}
		}
		else
		{
			res.push_back(it->data(0, Qt::UserRole).value<EagleData_Record_Id*>());
		}
	}

	return res;
}

//////////////////////////////////////////////////////////////////////////
// 设备列表 [11/16/2016 ejitec]
devListWidgets::devListWidgets(QWidget *parent)
:baseTreeWidget(parent)
{

	_timer = new QTimer(this);
	_timer->start(2000);
	
	connect(_timer, &QTimer::timeout, this, &devListWidgets::on_freshItems);

	_icons << QIcon(":/res/image/circle_green.png")  // normal
		<< QIcon(":/res/image/circle_blue.png")    // task
		<< QIcon(":/res/image/circle_red.png")   // rec
		<< QIcon(":/res/image/disk_warning.png");   // diskfull

//	connect(this, &QTreeWidget::itemChanged, this, &devListWidgets::on_ItemChanged);
}

// 必须在构造后，setui 之后进行 
void devListWidgets::heardInit()
{
	QStringList strHeader;
	for (int i = 0; i < CCD_TREELIST_COLUMN_NUM; i++)
	{
		strHeader << ccd_treelist_label[i]._label;
		setColumnWidth(i, ccd_treelist_label[i].colwidth);
	}
	setHeaderLabels(strHeader);
	setColumnCount(CCD_TREELIST_COLUMN_NUM);  // 列数
	setMinimumSize(this->minimumSizeHint());
	header()->setSectionResizeMode(QHeaderView::ResizeToContents);
	connect(this, &QTreeWidget::itemEntered, this, &devListWidgets::on_ItemEnter);
}


void devListWidgets::showPoptimeOut(QTreeWidgetItem* item)
{
	QPoint pos = viewport()->mapFromGlobal(cursor().pos());  // 坐标到 treewidget 的相对坐标
	// 将鼠标坐标转换当前的 viewPort的窗口  [11/14/2016 ejitec]
	QTreeWidgetItem* itemGot = this->itemAt(pos);

	if (itemGot != item)
	{
		return;
	}

	int device_id = 0;
	int ccd_serial = 0;
	bool bFind = false;

	delete _popUpMenu;
	_popUpMenu = NULL;


	if (item->type() == ITEM_PARENT)
	{
		DeviceClientData* data = static_cast<DeviceClientData*>(item->data(0, Qt::UserRole).value<baseCCDItemData*>());
		device_id = data->GetDevice();
	}
	else
	{
		CcdClientData* data = static_cast<CcdClientData*>(item->data(0, Qt::UserRole).value<baseCCDItemData*>());
		device_id = data->GetDevice();
		ccd_serial = data->GetCameraNo();
	}

	eagle_system_status status;
	EDeviceType device_type = EagleControl_GetDeviceType(device_id);
	memset(&status, 0, sizeof(status));
	EagleControl_GetSystemStatus(device_id, &status);

	eagle_capture_config ccdconfig;
	eagle_camera_disk_config disk;
	memset(&ccdconfig, 0, sizeof(ccdconfig));
	memset(&disk, 0, sizeof(disk));

	EagleControl_GetCameraDiskMapping(device_id, &disk);
	if (item->type() == ITEM_PARENT)
	{
		_popUpMenu = new DevicePopupWindow(this, device_id, &status, device_type);
	}
	else
	{
		ccdconfig.camera_no = ccd_serial;
		EagleControl_GetCameraCaptureParam(device_id, &ccdconfig);
		if (device_type == EDeviceTypeCL)
		{
			_popUpMenu = new CLCcdPopupWindow(this, &ccdconfig, disk.disk_reign[ccdconfig.camera_no - 1], device_id, device_type);
		}
			
		else if (device_type == EDeviceTypeSDI)
		{
			_popUpMenu = new SDICcdPopupWindow(this, &ccdconfig, disk.disk_reign[ccdconfig.camera_no - 1], device_id, device_type);
		}
	}

	_popUpMenu->setHeight();
	//_popUpMenu->exec(cursor().pos());
	_popUpMenu->exec(mapToGlobal(visualItemRect(item).bottomLeft() + QPoint(5,26)));
	//_curItem = nullptr;
}

devListWidgets::~devListWidgets()
{

}

void devListWidgets::mouseMoveEvent(QMouseEvent *event)
{

	QTreeWidgetItem* item = itemAt(event->pos());

	if (!item)  // 移出事件 [11/15/2016 ejitec]
	{
		delete _popUpMenu;
		_popUpMenu = NULL;
		return;
	}

	return QTreeWidget::mouseMoveEvent(event);  // 传递该事件 否则 移入受影响



// 	QTreeWidgetItem* item = itemAt(event->pos());
// 
// 	if (!item)  // 移出事件 [11/15/2016 ejitec]
// 	{
// 		delete _popUpMenu;
// 		_popUpMenu = NULL;
// 		_curItem = nullptr;
// 
// 		return;
// 	}
// 
// 	if (_curItem == item) 
// 	{
// 		return;
// 	}
// 
// 	_curItem = item;
// 
// 	QTimer::singleShot(500, this, [=]()
// 	{
// 		showPoptimeOut(item);
// 	});
// 
// 	return QTreeWidget::mouseMoveEvent(event); 
}

void devListWidgets::on_ItemEnter(QTreeWidgetItem* item, int column)
{
	if (_curItem == item)  // 与上次一致
	{
		return;
	}

	_curItem = item;
	delete _popUpMenu;
	_popUpMenu = NULL;


	QTimer::singleShot(500, this, [=]()
	{
		showPoptimeOut(item);
	});

}


// 在tablewidget 中 离开事件 在item离开时但是没有离开tree 时也会触发
void devListWidgets::leaveEvent(QEvent *event) 
{

#if 0

	// 鼠标不在 tree内 时 延时  删除 
	if (!this->rect().contains(viewport()->mapFromGlobal(cursor().pos())))
	{
		setMouseTracking(false);  // 禁用鼠标跟踪  防止这期间移入时
		QTimer::singleShot(500, this, [=]()
		{
			delete _popUpMenu;
			_popUpMenu = NULL;
			_curItem = nullptr;
			setMouseTracking(true);
		});
	}

#endif

	_curItem = nullptr;
	delete _popUpMenu;
	_popUpMenu = NULL;
}

// 设备更新时或启动时 [11/16/2016 ejitec]
void devListWidgets::RefreshItems()
{
	//clear();
}

// 定时 刷新 设备列宽状态 [11/18/2016 ejitec]
void devListWidgets::on_freshItems()
{
	QTreeWidgetItemIterator it(this);
	
	while (*it) 
	{
		QTreeWidgetItem* item = (*it);

		if (item->type() == ITEM_PARENT)
		{
			DeviceClientData* data = static_cast<DeviceClientData*>(item->data(0, Qt::UserRole).value<baseCCDItemData*>());
			int device_id = data->GetDevice();
			eagle_system_status system_status = CEagleDeviceMgr::GetInstance()->GetDeviceStatus(device_id);
			long disk_remain_threshold = 70;  // CEagleDeviceMgr::GetInstance()->GetDiskThreshold(device_id).toLong();

			for (int i = 0; i < system_status.disk_num; i++)
			{
				if (system_status.remained_volume[i] < disk_remain_threshold) {
					item->setIcon(0,_icons[3]);
				}
			}
			ChangeDeviceItemText(item, &system_status, EagleControl_GetDeviceType(device_id));
		}
		else
		{
			CcdClientData* data = static_cast<CcdClientData*>(item->data(0, Qt::UserRole).value<baseCCDItemData*>());
			int nImage = 0;
			int device_id = data->GetDevice();
			int ccd_serial = data->GetCameraNo();
			eagle_capture_config capture_status = CEagleDeviceMgr::GetInstance()->GetDeviceCcdCaptureStatus(device_id, ccd_serial);
			eagle_camera_disk_config disk_config = CEagleDeviceMgr::GetInstance()->GetDeviceDiskConfig(device_id);
			switch (capture_status.capture_status)
			{
			case ECaptureReady:
				nImage = 0;
				break;
			case ECaptureTasking:
				nImage = 1;
				break;
			case ECaptureRecording:
				nImage = 2;
				break;
			case ECapturePaused:
				nImage = 2;
				break;
			default:
				nImage = 0;
				break;
			}
			if (nImage >= 1)	// 如果设备在运行状态
			{
				if (item->parent() && item->parent()->checkState(0) != Qt::Checked)
				{
					item->parent()->setCheckState(0,Qt::Checked);
					EagleControl_CheckCamera(device_id, ccd_serial, true);
					CEagleDeviceMgr::GetInstance()->SetDeviceChecked(device_id, true);
				}
			}
			item->setIcon(0, _icons[nImage]);
			ChangeCcdItemText(item, &capture_status, disk_config.disk_reign[ccd_serial - 1], device_id);
		}
		//qDebug() << (*it)->type () << "," << (*it)->text(0);
		it++;
	}
}

// 设置设备 的单行状态列表 [10/19/2016 ejitec]
void devListWidgets::ChangeDeviceItemText(QTreeWidgetItem* ItemToChange, eagle_system_status* system_status, EDeviceType device_type)
{
	int i;
	//设备类型
	ItemToChange->setText(CCD_TREELIST_COLOMN_TYPEMODE, InterfaceType[device_type]);
	//温度
	ItemToChange->setText(CCD_TREELIST_COLOMN_TEMP, QString("").sprintf("%d ℃", system_status->fpga_tempture));
	//磁盘剩余容量
	for (i = 0; i < system_status->disk_num; i++)
	{
		ItemToChange->setText(CCD_TREELIST_COLOMN_DISK0 + i, QString("").sprintf("%dG", system_status->remained_volume[i]));
	}
	for (; i < 8; i++)
	{
		ItemToChange->setText(CCD_TREELIST_COLOMN_DISK0 + i, "×");
	}
	//剩余列表
	for (i = CCD_TREELIST_COLOMN_COLUMN; i <= CCD_TREELIST_COLOMN_STATUS; i++)
	{
		ItemToChange->setText(i, "×");
	}
}

// 设置CCD 的单行状态信息列表 [10/19/2016 ejitec]
void devListWidgets::ChangeCcdItemText(QTreeWidgetItem* ItemToChange, eagle_capture_config* capture_status, unsigned char disk_mapping, int device_id)
{
	EDeviceType device_type = EagleControl_GetDeviceType(device_id);
	//设备类型	
	QString content;
	if (device_type == EDeviceTypeCL)
		content = CL_Mode_Str[GetCameraMode(capture_status->taps, capture_status->color_depth)];
	else if (device_type == EDeviceTypeSDI)
		content = SDI_Mode_Str[CEagleDeviceMgr::GetInstance()->GetSdiMode(device_id)];
	ItemToChange->setText(CCD_TREELIST_COLOMN_TYPEMODE, content);
	int column = capture_status->column;
	int color_depth = capture_status->color_depth;

#ifdef CHENGGS_VERSION 
	if (capture_status->camera_no == 3 && CHENGGS_VERSION == 2)
	{
		column /= 2;
		color_depth = (color_depth * 3) / 2;
	}

	if (capture_status->camera_no == 2 && CHENGGS_VERSION == 3)
	{
		column /= 4;
		color_depth = color_depth * 3;  //  [11/11/2016 ejitec]
	}

#endif

	if (device_type == EDeviceTypeCL)
		content = QString("").sprintf("%d", column);
	else
		content = "×";
	ItemToChange->setText(CCD_TREELIST_COLOMN_COLUMN, content);
	ItemToChange->setText(CCD_TREELIST_COLOMN_LINE, QString("").sprintf("%d", capture_status->line));
	ItemToChange->setText(CCD_TREELIST_COLOMN_COLORDEPTH, QString("").sprintf("%d", color_depth));

	if (device_type == EDeviceTypeCL)
		content = QString("").sprintf("%d", capture_status->taps);
	else
		content = "×";
	ItemToChange->setText(CCD_TREELIST_COLOMN_TAPS, content);
	ItemToChange->setText(CCD_TREELIST_COLOMN_STATUS, GetCaptureStatus(capture_status->capture_status));

#ifdef  CHENGGS_VERSION
	// 状态列 显示光纤 通断 [10/25/2016 ejitec]
	int nRet = 0;
	if (CEagleDeviceMgr::GetInstance()->IsFrebOnLine(device_id, capture_status->camera_no, nRet))
	{
		ItemToChange->setText(CCD_TREELIST_COLOMN_STATUS, GetCaptureStatus(capture_status->capture_status + nRet));
	}

#endif //  CHENGGS_VERSION

	for (int i = 0; i < 8; i++)
	{
		if (0x01 & (disk_mapping >> i))
			content = "√";
		else
			content = "×";
		ItemToChange->setText(CCD_TREELIST_COLOMN_DISK0 + i, content);
	}
}

void devListWidgets::on_ItemChanged(QTreeWidgetItem* item, int column)
{
	if (column != 0)
	{
		return;
	}

	// 设置 checkable  会激发该事件  防止递归
	disConnectCheck();
	int nRet = 0;
	if (item->type() == ITEM_PARENT)
	{
		DeviceClientData* data = static_cast<DeviceClientData*>(item->data(0, Qt::UserRole).value<baseCCDItemData*>());
		CEagleDeviceMgr::GetInstance()->SetDeviceChecked(data->GetDevice(), item->checkState(0) == Qt::Checked);

		QTreeWidgetItemIterator it(item);
		while (*(++it))
		{
			QTreeWidgetItem* cur = *it;
			if (cur->type() == ITEM_PARENT)  // 到下一个设备根退出
			{
				break;
			}
			cur->setCheckState(0, item->checkState(0)); //子节点也选中
			CcdClientData* data = static_cast<CcdClientData*>(cur->data(0, Qt::UserRole).value<baseCCDItemData*>());
			nRet = EagleControl_CheckCamera(data->GetDevice(), data->GetCameraNo(), item->checkState(0) == Qt::Checked);
		}
	}
	else
	{
		CcdClientData* data = static_cast<CcdClientData*>(item->data(0, Qt::UserRole).value<baseCCDItemData*>());
		nRet = EagleControl_CheckCamera(data->GetDevice(), data->GetCameraNo(), item->checkState(0) == Qt::Checked);
		if (item->checkState(0) == Qt::Checked)
		{
			//父节点 选中
			item->parent()->setCheckState(0, Qt::Checked);
			CEagleDeviceMgr::GetInstance()->SetDeviceChecked(data->GetDevice(),true);
		}
		else
		{
			QTreeWidgetItem* parent = item->parent();
			int count = parent->childCount();
			bool isAllUnCheck = true;
			for (int i = 0; i < count; i++)
			{
				if (parent->child(i) != item)
				{
					if (parent->child(i)->checkState(0) == Qt::Checked)
					{
						isAllUnCheck = false;
						break;
					}
				}
			}

			if (isAllUnCheck)
			{
				//是子节点
				item->parent()->setCheckState(0, Qt::Unchecked);
				CEagleDeviceMgr::GetInstance()->SetDeviceChecked(data->GetDevice(), false);
			}
		}
	}

	// 重新连接 [11/16/2016 ejitec]
	setCheckConnection();
}

void devListWidgets::setCheckConnection()
{
	connect(this, &QTreeWidget::itemChanged, this, &devListWidgets::on_ItemChanged);
}

void devListWidgets::disConnectCheck()
{
	disconnect(this, &QTreeWidget::itemChanged, this, &devListWidgets::on_ItemChanged);
}
